package com.kindel.controller.weixin;

import com.alibaba.fastjson.JSON;
import com.common.model.enums.ErrorCode;
import com.common.model.response.JsonResponse;
import com.common.model.view.wechat.applet.JsCode2SessionResView;
import com.common.model.view.wechat.applet.WechatAppletUserInfo;
import com.common.util.AES128Util;
import com.common.util.ApplicationUtils;
import com.kindel.service.weixin.WeixinService;
import com.kindel.util.Config4kindlecp;
import com.kindel.util.KindleUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by demongao on 2017/9/4.
 */
@Controller
@RequestMapping("kindel/weixin")
@EnableAutoConfiguration
@Api(value = "微信接口", description = "")
public class weixinController {
    private Logger logger = Logger.getLogger(weixinController.class);

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private WeixinService weixinService;


    @RequestMapping(value = "/getSession3rd",method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "获取Session3rd")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "code", value = "用户登录后的code(用来换取session_3rd)", required = false),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "session_3rd", value = "session_3rd", required = false)
    })
    public JsonResponse<Map<String, Object>> getSession3rd(String code, String session_3rd){

        logger.info("code:"+code +"\t" + "session_3rd:" +session_3rd);
        //判断code是否为空
        if (null == code || code.isEmpty()) {
            return new JsonResponse<>(ErrorCode.FAILED_KINDLECP_CODE_IS_NULL);
        }

        //换取session_3rd
        JsCode2SessionResView jsCode2SessionResView = restTemplate.getForObject(Config4kindlecp.JSCODE2SESSION_API,
                JsCode2SessionResView.class, code);

        //判断是否换取成功
        if (jsCode2SessionResView.getErrcode() !=null){
            return new JsonResponse<>(ErrorCode.FAILED_KINDLECP_JSCODE2SESSION);
        }

        // 判断提交时 session_3rd 是否为空，若不是则从redis中删除
        if (null != session_3rd && !session_3rd.isEmpty()) {
            logger.info("删除redis的session_3rd");
            weixinService.removeSession3rdFromRedis(session_3rd);
            weixinService.removeWechatAppletUserInfoFromRedis(session_3rd);
        }

        session_3rd = KindleUtil.getRandomStr(32);
        weixinService.saveSession3rdToRedis(session_3rd, jsCode2SessionResView);

        logger.info("session_3rd:" + session_3rd + " jsCode2SessionResView:" + jsCode2SessionResView);

        Map<String,Object> resultMap = new HashMap<String,Object>();

        resultMap.put("session_3rd",session_3rd);

        return new JsonResponse<Map<String, Object>>(ErrorCode.SUCCESS,resultMap);
    }

    @RequestMapping(value = "/getUserInfo",method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value = "获取用户信息，通过 session_3rd 和 iv解码 encryptedData 获取 unionId")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "session_3rd", value = "session_3rd", required = false),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "userInfoEncryptedData", value = "用户信息对象,包括敏感数据在内的完整用户信息的加密数据", required = false),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "userInfoIv", value = "加密算法的初始向量", required = false),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "userInfoRawData", value = "用户信息对象,不包括敏感信息的原始数据字符串，用于计算签名。", required = false),
            @ApiImplicitParam(paramType = "query", dataType = "String", name = "userInfoSignature", value = "使用 sha1( rawData + sessionkey ) 得到字符串，用于校验用户信息", required = false)
    })
    public JsonResponse<Map<String, Object>> getUserInfo(String session_3rd, String userInfoEncryptedData, String userInfoIv, String userInfoRawData, String userInfoSignature){
        Map<String,Object> resultMap = new HashMap<String,Object>();

        if(session_3rd == null || session_3rd.isEmpty() ){
            return new JsonResponse<Map<String, Object>>(ErrorCode.FAILED_KINDLECP_SESSION_3RD_IS_NULL);
        }
        if(userInfoEncryptedData == null || userInfoEncryptedData.isEmpty()){
            return new JsonResponse<Map<String, Object>>(ErrorCode.FAILED_KINDLECP_USERINFOENCRYPTEDDATA_IS_NULL);
        }
        if(userInfoIv == null || userInfoIv.isEmpty()){
            return new JsonResponse<Map<String, Object>>(ErrorCode.FAILED_KINDLECP_USERINFOIV_IS_NULL);
        }
        if(userInfoRawData == null || userInfoRawData.isEmpty()){
            return new JsonResponse<Map<String, Object>>(ErrorCode.FAILED_KINDLECP_USERINFORAWDATA_IS_NULL);
        }
        if(userInfoSignature == null || userInfoSignature.isEmpty()){
            return new JsonResponse<Map<String, Object>>(ErrorCode.FAILED_KINDLECP_USERINFOSIGNATURE_IS_NULL);
        }
        //
        JsCode2SessionResView jsCode2SessionResView = weixinService.loadSession3rdFromRedis(session_3rd);
        if(jsCode2SessionResView == null){
            return new JsonResponse<Map<String, Object>>(ErrorCode.FAILED_KINDLECP_SESSION_3RD_EXPIRE);
        }
        String signature = ApplicationUtils.sha1Hex(userInfoRawData + jsCode2SessionResView.getSession_key());

        if(!userInfoSignature.equals(signature)){

            return new JsonResponse<Map<String, Object>>(ErrorCode.FAILED_KINDLECP_SIGNATUR_IS_ERROR);
        }
        logger.info("签名认证成功");

        // 解密userInfo
        String userInfoStr = null;
        try {
            userInfoStr = AES128Util.wxDecrypt(URLDecoder.decode(userInfoEncryptedData, "UTF-8"),
                    jsCode2SessionResView.getSession_key(), userInfoIv);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return new JsonResponse<>(ErrorCode.FAILED_KINDLECP_URLDECODER_EXCEPTION);
        }

        if (null != userInfoStr && !userInfoStr.isEmpty()) {
            // 保存或更新 userInfo 信息
            WechatAppletUserInfo wechatAppletUserInfo = JSON.parseObject(userInfoStr, WechatAppletUserInfo.class);


            if(weixinService.saveOrUpdateWechatAppletUserInfo(wechatAppletUserInfo)){
                weixinService.saveWechatAppletUserInfoToRedis(session_3rd, wechatAppletUserInfo);
            }
            logger.info(wechatAppletUserInfo);

            resultMap.put("userInfo",wechatAppletUserInfo);
        }
        return new JsonResponse<Map<String, Object>>(ErrorCode.SUCCESS, resultMap);
    }
}
